﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using KursnaListaService.Models;

namespace KursnaListaService
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            StartBackgroundWorker();
        }

        void StartBackgroundWorker()
        {
            // Code that runs on application startup
            var worker = new BackgroundWorker();
            worker.DoWork += DoWork;
            worker.WorkerReportsProgress = false;
            worker.WorkerSupportsCancellation = true;
            worker.RunWorkerCompleted += WorkerCompleted;

            Application.Add("BackgroundWorker", worker);

            // Calling the DoWork Method Asynchronously
            worker.RunWorkerAsync(); //we can also pass parameters to the async method....

        }

        private static void DoWork(object sender, DoWorkEventArgs e)
        {
            Get();
        }

        private static void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var worker = sender as BackgroundWorker;
            if (worker != null)
            {
                // sleep for 20 secs and again call DoWork to get FxRates..we can increase the time to sleep and make it configurable to the needs
                System.Threading.Thread.Sleep(5 * 60 * 1000);
                worker.RunWorkerAsync();
            }
        }

        void Application_End(object sender, EventArgs e)
        {
            var worker = Application["BackgroundWorker"] as BackgroundWorker;
            if (worker != null)
            {
                worker.CancelAsync();
            }
        }

        public static IEnumerable<string> Get()
        {
            var result = new List<string>();
            var today = DateTime.Now.Date;

            var repo = new Repository(ConfigurationManager.ConnectionStrings["DataConnection"].ConnectionString);

            var date = repo.GetNajnovijiDan();

            if (date == null)
            {
                date = new DateTime(2013, 1, 3);
            }
            else
            {
                date = date.Value.AddDays(1);
            }

            ServicePointManager.Expect100Continue = false;
            while (date <= today)
            {
                if (date.Value.DayOfWeek != DayOfWeek.Saturday
                    && date.Value.DayOfWeek != DayOfWeek.Sunday)
                {
                    result.Add(date.Value.ToShortDateString());
                    SyncData(date.Value, repo);
                }
                date = date.Value.AddDays(1);
            }

            return result;
        }

        private static void SyncData(DateTime date, IRepository repo)
        {
            KursnaListaZaDan kursnaListaZaDan = null;
            do
            {
                kursnaListaZaDan = new KursnaListaZaDan
                                       {
                                           ZaEfektivniStraniNovac = new List<StavkaKursneListe>(),
                                           ZaDevize = new List<StavkaKursneListe>(),
                                           SrednjiKurs = new List<StavkaKursneListe>(),
                                       };

                var client = new WebClient();
                client.Headers.Add(HttpRequestHeader.Accept, "text/html, application/xhtml+xml, */*");
                client.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
                client.Headers.Add(HttpRequestHeader.AcceptLanguage,
                                   "en-US,en;q=0.8,sr-Latn-RS;q=0.7,sr-Latn;q=0.5,sr-Cyrl-RS;q=0.3,sr-Cyrl;q=0.2");
                client.Headers.Add(HttpRequestHeader.UserAgent,
                                   "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

                var result = client.DownloadString("http://www.nbs.rs/kursnaListaModul/naZeljeniDan.faces?lang=lat");
                var cookie = client.ResponseHeaders["Set-Cookie"];
                var sessionMatch = Regex.Match(cookie, @"JSESSIONID=([A-F0-9]+);", RegexOptions.IgnoreCase);
                var session = sessionMatch.Groups[1].Value;
                var facesViewMatch = Regex.Match(result, @"_id([0-9]+):_id([0-9]+)", RegexOptions.IgnoreCase);
                var facesView1 = facesViewMatch.Groups[1].Value;
                var facesView2 = facesViewMatch.Groups[2].Value;
                var r2 = QueryData(date, 2, string.Format("JSESSIONID={0};", session),
                                   string.Format("_id{0}%3A_id{1}", facesView1, facesView2));
                foreach (var line in r2)
                {
                    var fields = line.Split(',');
                    var dateFields = fields[1].Split('.').Select(int.Parse).ToArray();
                    var currentDate = new DateTime(dateFields[2], dateFields[1], dateFields[0]);
                    if (currentDate != date)
                        return;
                    kursnaListaZaDan.Datum = currentDate;
                    kursnaListaZaDan.Broj = int.Parse(fields[0]);
                    kursnaListaZaDan.ZaEfektivniStraniNovac.Add(new StavkaKursneListe
                                                                    {
                                                                        SifraValute = int.Parse(fields[2]),
                                                                        NazivZemlje = fields[3],
                                                                        OznakaValute = fields[4],
                                                                        VaziZa = int.Parse(fields[5]),
                                                                        KupovniKurs = decimal.Parse(fields[6]),
                                                                        ProdajniKurs = decimal.Parse(fields[7])
                                                                    });
                }
                System.Threading.Thread.Sleep(500);
                var r1 = QueryData(date, 1, string.Format("JSESSIONID={0};", session),
                                   string.Format("_id{0}%3A_id{1}", facesView1, facesView2));
                foreach (var line in r1)
                {
                    var fields = line.Split(',');
                    var dateFields = fields[1].Split('.').Select(int.Parse).ToArray();
                    var currentDate = new DateTime(dateFields[2], dateFields[1], dateFields[0]);
                    if (currentDate != date)
                        return;
                    kursnaListaZaDan.ZaDevize.Add(new StavkaKursneListe
                                                      {
                                                          SifraValute = int.Parse(fields[2]),
                                                          NazivZemlje = fields[3],
                                                          OznakaValute = fields[4],
                                                          VaziZa = int.Parse(fields[5]),
                                                          KupovniKurs = decimal.Parse(fields[6]),
                                                          ProdajniKurs = decimal.Parse(fields[7])
                                                      });
                }
                System.Threading.Thread.Sleep(500);
                var r3 = QueryData(date, 3, string.Format("JSESSIONID={0};", session),
                                   string.Format("_id{0}%3A_id{1}", facesView1, facesView2));
                foreach (var line in r3)
                {
                    var fields = line.Split(',');
                    var dateFields = fields[1].Split('.').Select(int.Parse).ToArray();
                    var currentDate = new DateTime(dateFields[2], dateFields[1], dateFields[0]);
                    if (currentDate != date)
                        return;
                    kursnaListaZaDan.SrednjiKurs.Add(new StavkaKursneListe
                                                         {
                                                             SifraValute = int.Parse(fields[2]),
                                                             NazivZemlje = fields[3],
                                                             OznakaValute = fields[4],
                                                             VaziZa = int.Parse(fields[5]),
                                                             SrednjiKurs = decimal.Parse(fields[6]),
                                                         });
                }
                System.Threading.Thread.Sleep(500);
            } while (kursnaListaZaDan.SrednjiKurs.Count == 0 ||
                     kursnaListaZaDan.ZaDevize.Count == 0 ||
                     kursnaListaZaDan.ZaEfektivniStraniNovac.Count == 0
                );
            repo.Update(kursnaListaZaDan);
        }

        private static string[] QueryData(DateTime date, int vrsta, string session, string facesView)
        {
            var client = new WebClient();
            client.Headers.Add(HttpRequestHeader.Accept, "text/html, application/xhtml+xml, */*");
            client.Headers.Add(HttpRequestHeader.Referer, "http://www.nbs.rs/kursnaListaModul/naZeljeniDan.faces?lang=lat");
            client.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.8,sr-Latn-RS;q=0.7,sr-Latn;q=0.5,sr-Cyrl-RS;q=0.3,sr-Cyrl;q=0.2");
            client.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
            client.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
            client.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
            client.Headers.Add(HttpRequestHeader.AcceptCharset, "utf-8;");
            client.Headers.Add(HttpRequestHeader.Cookie, session);

            var result = Encoding.UTF8.GetString(client.UploadData("http://www.nbs.rs/kursnaListaModul/naZeljeniDan.faces",
                                              Encoding.UTF8.GetBytes(string.Format(
                                                   "index%3AbrKursneListe=&index%3Ayear={2:0000}&index%3AinputCalendar1={0:00}.{1:00}.{2:0000}.&index%3Avrsta={4}&index%3Aprikaz=1&index%3AbuttonShow=Prika%C5%BEi&com.sun.faces.VIEW={3}&index=index",
                                                   date.Day, date.Month, date.Year, facesView, vrsta))));
            return result.Split('\n').Skip(1).Where(s => !string.IsNullOrEmpty(s)).ToArray();
        }

    }
}